import obsws_python as obs
import time
import logging
from typing import Optional, Dict, Any


class OBSClient:
    """OBS Studio WebSocket客户端"""
    
    def __init__(self, host: str = "localhost", port: int = 4455, password: str = ""):
        """
        初始化OBS客户端
        
        Args:
            host: OBS WebSocket服务器地址
            port: OBS WebSocket端口
            password: 连接密码
        """
        self.host = host
        self.port = port
        self.password = password
        self.ws = None
        self.connected = False
        
        # 配置日志
        logging.basicConfig(level=logging.INFO)
        self.logger = logging.getLogger(__name__)
        
    def connect(self) -> bool:
        """连接到OBS Studio"""
        try:
            self.ws = obs.ReqClient(
                host=self.host,
                port=self.port,
                password=self.password
            )
            self.connected = True
            self.logger.info(f"成功连接到OBS Studio: {self.host}:{self.port}")
            return True
        except Exception as e:
            self.logger.error(f"连接OBS Studio失败: {e}")
            self.connected = False
            return False
    
    def disconnect(self):
        """断开连接"""
        if self.ws:
            self.ws.disconnect()
            self.connected = False
            self.logger.info("已断开OBS连接")
    
    def is_connected(self) -> bool:
        """检查连接状态"""
        return self.connected
    
    def get_version(self) -> Optional[Dict[str, Any]]:
        """获取OBS版本信息"""
        if not self.connected:
            self.logger.error("未连接到OBS")
            return None
        
        try:
            response = self.ws.get_version()
            # 新版obsws-python返回的对象结构处理
            if hasattr(response, 'attrs') and callable(response.attrs):
                attrs = response.attrs()
                # 如果attrs返回的是列表，尝试转换为dict
                if isinstance(attrs, list) and len(attrs) > 0:
                    if hasattr(attrs[0], '__dict__'):
                        return attrs[0].__dict__
                    else:
                        return {"version_data": attrs}
                elif isinstance(attrs, dict):
                    return attrs
                else:
                    return {"raw_data": attrs}
            elif hasattr(response, '__dict__'):
                return response.__dict__
            else:
                return {"raw_response": str(response)}
        except Exception as e:
            self.logger.error(f"获取版本信息失败: {e}")
            return None
    
    def get_scene_list(self) -> Optional[list]:
        """获取场景列表"""
        if not self.connected:
            self.logger.error("未连接到OBS")
            return None
        
        try:
            response = self.ws.get_scene_list()
            if hasattr(response, 'scenes'):
                return response.scenes
            elif hasattr(response, 'attrs'):
                return response.attrs().get('scenes', [])
            else:
                return response.__dict__.get('scenes', [])
        except Exception as e:
            self.logger.error(f"获取场景列表失败: {e}")
            return None
    
    def get_current_scene(self) -> Optional[str]:
        """获取当前场景名称"""
        if not self.connected:
            self.logger.error("未连接到OBS")
            return None
        
        try:
            response = self.ws.get_current_program_scene()
            if hasattr(response, 'scene_name'):
                return response.scene_name
            elif hasattr(response, 'sceneName'):
                return response.sceneName
            elif hasattr(response, 'attrs'):
                attrs = response.attrs()
                return attrs.get('sceneName') or attrs.get('scene_name')
            else:
                return response.__dict__.get('sceneName') or response.__dict__.get('scene_name')
        except Exception as e:
            self.logger.error(f"获取当前场景失败: {e}")
            return None
    
    def set_current_scene(self, scene_name: str) -> bool:
        """切换到指定场景"""
        if not self.connected:
            self.logger.error("未连接到OBS")
            return False
        
        try:
            self.ws.set_current_program_scene(scene_name)
            self.logger.info(f"已切换到场景: {scene_name}")
            return True
        except Exception as e:
            self.logger.error(f"切换场景失败: {e}")
            return False
    
    def get_source_list(self, scene_name: str) -> Optional[list]:
        """获取指定场景的源列表"""
        if not self.connected:
            self.logger.error("未连接到OBS")
            return None
        
        try:
            response = self.ws.get_scene_item_list(scene_name)
            if hasattr(response, 'scene_items'):
                return response.scene_items
            elif hasattr(response, 'sceneItems'):
                return response.sceneItems
            elif hasattr(response, 'attrs'):
                attrs = response.attrs()
                return attrs.get('sceneItems') or attrs.get('scene_items', [])
            else:
                return response.__dict__.get('sceneItems') or response.__dict__.get('scene_items', [])
        except Exception as e:
            self.logger.error(f"获取源列表失败: {e}")
            return None
    
    def __enter__(self):
        """上下文管理器入口"""
        self.connect()
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        """上下文管理器出口"""
        self.disconnect()
        return False